package com.free.bsf.health.memoryParse;

import com.free.bsf.core.util.StringUtils;
import com.free.bsf.core.util.WarnUtils;
import com.free.bsf.core.util.WebUtils;
import com.free.bsf.health.config.MemoryParseProperties;
import lombok.val;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

import java.util.Properties;

/**
 * @author: chejiangyi
 * @version: 2019-08-02 09:43
 **/
@Intercepts({
        @Signature(method = "query", type = Executor.class, args = { MappedStatement.class, Object.class,
                RowBounds.class, ResultHandler.class }),
        @Signature(method = "query", type = Executor.class, args = { MappedStatement.class, Object.class,
                RowBounds.class, ResultHandler.class, CacheKey.class,BoundSql.class}) })
public class MemorySqlMybatisInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        val result = invocation.proceed();
        long maxsize= MemoryRecordUtils.checkResultSize(result);
        if(maxsize> MemoryParseProperties.Default().getBsfHealthMemorySqlQueryMaxSize()){
            //特殊场景立即报警
            WarnUtils.notify(WarnUtils.ALARM_ERROR,
                    "sql单次查询超过"+ MemoryParseProperties.Default().getBsfHealthMemorySqlQueryMaxSize()+"条",
                    "size:"+maxsize+"\n"+
                            "url:"+ StringUtils.nullToEmpty(WebUtils.getRequestURI())+"\n"+
                            "sql:"+StringUtils.nullToEmpty(getSql(invocation)));
        }
        return result;
    }

    private String getSql(Invocation invocation){
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        // 得到sql语句
        Object parameter = null;
        if (invocation.getArgs().length > 1) {
            parameter = invocation.getArgs()[1];
        }
        BoundSql boundSql = mappedStatement.getBoundSql(parameter);
        String sql = boundSql.getSql();
        return sql.replace("\r","").replace("\n","");
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }

}